001 /* 002 * Copyright 2001-2007 Stephen Colebourne 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.joda.time; 017 018 import java.io.IOException; 019 import java.io.ObjectInputStream; 020 import java.io.ObjectOutputStream; 021 import java.io.Serializable; 022 import java.util.Calendar; 023 import java.util.Date; 024 import java.util.HashSet; 025 import java.util.Locale; 026 import java.util.Set; 027 028 import org.joda.time.base.BaseLocal; 029 import org.joda.time.chrono.ISOChronology; 030 import org.joda.time.convert.ConverterManager; 031 import org.joda.time.convert.PartialConverter; 032 import org.joda.time.field.AbstractReadableInstantFieldProperty; 033 import org.joda.time.format.DateTimeFormat; 034 import org.joda.time.format.ISODateTimeFormat; 035 036 /** 037 * LocalTime is an immutable time class representing a time 038 * without a time zone. 039 * <p> 040 * LocalTime implements the {@link ReadablePartial} interface. 041 * To do this, the interface methods focus on the key fields - 042 * HourOfDay, MinuteOfHour, SecondOfMinute and MillisOfSecond. 043 * However, <b>all</b> time fields may in fact be queried. 044 * <p> 045 * Calculations on LocalTime are performed using a {@link Chronology}. 046 * This chronology will be set internally to be in the UTC time zone 047 * for all calculations. 048 * 049 * <p>Each individual field can be queried in two ways: 050 * <ul> 051 * <li><code>getHourOfDay()</code> 052 * <li><code>hourOfDay().get()</code> 053 * </ul> 054 * The second technique also provides access to other useful methods on the 055 * field: 056 * <ul> 057 * <li>numeric value 058 * <li>text value 059 * <li>short text value 060 * <li>maximum/minimum values 061 * <li>add/subtract 062 * <li>set 063 * <li>rounding 064 * </ul> 065 * 066 * <p> 067 * LocalTime is thread-safe and immutable, provided that the Chronology is as well. 068 * All standard Chronology classes supplied are thread-safe and immutable. 069 * 070 * @author Stephen Colebourne 071 * @since 1.3 072 */ 073 public final class LocalTime 074 extends BaseLocal 075 implements ReadablePartial, Serializable { 076 077 /** Serialization lock */ 078 private static final long serialVersionUID = -12873158713873L; 079 080 /** Constant for midnight. */ 081 public static final LocalTime MIDNIGHT = new LocalTime(0, 0, 0, 0); 082 083 /** The index of the hourOfDay field in the field array */ 084 private static final int HOUR_OF_DAY = 0; 085 /** The index of the minuteOfHour field in the field array */ 086 private static final int MINUTE_OF_HOUR = 1; 087 /** The index of the secondOfMinute field in the field array */ 088 private static final int SECOND_OF_MINUTE = 2; 089 /** The index of the millisOfSecond field in the field array */ 090 private static final int MILLIS_OF_SECOND = 3; 091 /** Set of known duration types. */ 092 private static final Set TIME_DURATION_TYPES = new HashSet(); 093 static { 094 TIME_DURATION_TYPES.add(DurationFieldType.millis()); 095 TIME_DURATION_TYPES.add(DurationFieldType.seconds()); 096 TIME_DURATION_TYPES.add(DurationFieldType.minutes()); 097 TIME_DURATION_TYPES.add(DurationFieldType.hours()); 098 } 099 100 /** The local millis from 1970-01-01T00:00:00 */ 101 private long iLocalMillis; 102 /** The chronology to use, in UTC */ 103 private Chronology iChronology; 104 105 //----------------------------------------------------------------------- 106 /** 107 * Constructs a LocalTime from the specified millis of day using the 108 * ISO chronology. 109 * <p> 110 * The millisOfDay value may exceed the number of millis in one day, 111 * but additional days will be ignored. 112 * This method uses the UTC time zone internally. 113 * 114 * @param millisOfDay the number of milliseconds into a day to convert 115 */ 116 public static LocalTime fromMillisOfDay(long millisOfDay) { 117 return fromMillisOfDay(millisOfDay, null); 118 } 119 120 /** 121 * Constructs a LocalTime from the specified millis of day using the 122 * specified chronology. 123 * <p> 124 * The millisOfDay value may exceed the number of millis in one day, 125 * but additional days will be ignored. 126 * This method uses the UTC time zone internally. 127 * 128 * @param millisOfDay the number of milliseconds into a day to convert 129 * @param chrono the chronology, null means ISO chronology 130 */ 131 public static LocalTime fromMillisOfDay(long millisOfDay, Chronology chrono) { 132 chrono = DateTimeUtils.getChronology(chrono).withUTC(); 133 return new LocalTime(millisOfDay, chrono); 134 } 135 136 //----------------------------------------------------------------------- 137 /** 138 * Constructs a LocalTime from a <code>java.util.Calendar</code> 139 * using exactly the same field values. 140 * <p> 141 * Each field is queried from the Calendar and assigned to the LocalTime. 142 * This is useful if you have been using the Calendar as a local time, 143 * ignoring the zone. 144 * <p> 145 * One advantage of this method is that this method is unaffected if the 146 * version of the time zone data differs between the JDK and Joda-Time. 147 * That is because the local field values are transferred, calculated using 148 * the JDK time zone data and without using the Joda-Time time zone data. 149 * <p> 150 * This factory method ignores the type of the calendar and always 151 * creates a LocalTime with ISO chronology. It is expected that you 152 * will only pass in instances of <code>GregorianCalendar</code> however 153 * this is not validated. 154 * 155 * @param calendar the Calendar to extract fields from 156 * @return the created LocalTime 157 * @throws IllegalArgumentException if the calendar is null 158 * @throws IllegalArgumentException if the date is invalid for the ISO chronology 159 */ 160 public static LocalTime fromCalendarFields(Calendar calendar) { 161 if (calendar == null) { 162 throw new IllegalArgumentException("The calendar must not be null"); 163 } 164 return new LocalTime( 165 calendar.get(Calendar.HOUR_OF_DAY), 166 calendar.get(Calendar.MINUTE), 167 calendar.get(Calendar.SECOND), 168 calendar.get(Calendar.MILLISECOND) 169 ); 170 } 171 172 /** 173 * Constructs a LocalTime from a <code>java.util.Date</code> 174 * using exactly the same field values. 175 * <p> 176 * Each field is queried from the Date and assigned to the LocalTime. 177 * This is useful if you have been using the Date as a local time, 178 * ignoring the zone. 179 * <p> 180 * One advantage of this method is that this method is unaffected if the 181 * version of the time zone data differs between the JDK and Joda-Time. 182 * That is because the local field values are transferred, calculated using 183 * the JDK time zone data and without using the Joda-Time time zone data. 184 * <p> 185 * This factory method always creates a LocalTime with ISO chronology. 186 * 187 * @param date the Date to extract fields from 188 * @return the created LocalTime 189 * @throws IllegalArgumentException if the calendar is null 190 * @throws IllegalArgumentException if the date is invalid for the ISO chronology 191 */ 192 public static LocalTime fromDateFields(Date date) { 193 if (date == null) { 194 throw new IllegalArgumentException("The date must not be null"); 195 } 196 return new LocalTime( 197 date.getHours(), 198 date.getMinutes(), 199 date.getSeconds(), 200 (((int) (date.getTime() % 1000)) + 1000) % 1000 201 ); 202 } 203 204 //----------------------------------------------------------------------- 205 /** 206 * Constructs an instance set to the current local time evaluated using 207 * ISO chronology in the default zone. 208 * <p> 209 * Once the constructor is completed, the zone is no longer used. 210 */ 211 public LocalTime() { 212 this(DateTimeUtils.currentTimeMillis(), ISOChronology.getInstance()); 213 } 214 215 /** 216 * Constructs an instance set to the current local time evaluated using 217 * ISO chronology in the specified zone. 218 * <p> 219 * If the specified time zone is null, the default zone is used. 220 * Once the constructor is completed, the zone is no longer used. 221 * 222 * @param zone the time zone, null means default zone 223 */ 224 public LocalTime(DateTimeZone zone) { 225 this(DateTimeUtils.currentTimeMillis(), ISOChronology.getInstance(zone)); 226 } 227 228 /** 229 * Constructs an instance set to the current local time evaluated using 230 * specified chronology and zone. 231 * <p> 232 * If the chronology is null, ISO chronology in the default time zone is used. 233 * Once the constructor is completed, the zone is no longer used. 234 * 235 * @param chronology the chronology, null means ISOChronology in default zone 236 */ 237 public LocalTime(Chronology chronology) { 238 this(DateTimeUtils.currentTimeMillis(), chronology); 239 } 240 241 //----------------------------------------------------------------------- 242 /** 243 * Constructs an instance set to the local time defined by the specified 244 * instant evaluated using ISO chronology in the default zone. 245 * <p> 246 * Once the constructor is completed, the zone is no longer used. 247 * 248 * @param instant the milliseconds from 1970-01-01T00:00:00Z 249 */ 250 public LocalTime(long instant) { 251 this(instant, ISOChronology.getInstance()); 252 } 253 254 /** 255 * Constructs an instance set to the local time defined by the specified 256 * instant evaluated using ISO chronology in the specified zone. 257 * <p> 258 * If the specified time zone is null, the default zone is used. 259 * Once the constructor is completed, the zone is no longer used. 260 * 261 * @param instant the milliseconds from 1970-01-01T00:00:00Z 262 * @param zone the time zone, null means default zone 263 */ 264 public LocalTime(long instant, DateTimeZone zone) { 265 this(instant, ISOChronology.getInstance(zone)); 266 } 267 268 /** 269 * Constructs an instance set to the local time defined by the specified 270 * instant evaluated using the specified chronology. 271 * <p> 272 * If the chronology is null, ISO chronology in the default zone is used. 273 * Once the constructor is completed, the zone is no longer used. 274 * 275 * @param instant the milliseconds from 1970-01-01T00:00:00Z 276 * @param chronology the chronology, null means ISOChronology in default zone 277 */ 278 public LocalTime(long instant, Chronology chronology) { 279 chronology = DateTimeUtils.getChronology(chronology); 280 281 long localMillis = chronology.getZone().getMillisKeepLocal(DateTimeZone.UTC, instant); 282 chronology = chronology.withUTC(); 283 iLocalMillis = chronology.millisOfDay().get(localMillis); 284 iChronology = chronology; 285 } 286 287 //----------------------------------------------------------------------- 288 /** 289 * Constructs an instance from an Object that represents a datetime. 290 * <p> 291 * If the object contains no chronology, <code>ISOChronology</code> is used. 292 * If the object contains no time zone, the default zone is used. 293 * Once the constructor is completed, the zone is no longer used. 294 * <p> 295 * The recognised object types are defined in 296 * {@link org.joda.time.convert.ConverterManager ConverterManager} and 297 * include ReadablePartial, ReadableInstant, String, Calendar and Date. 298 * The String formats are described by {@link ISODateTimeFormat#localTimeParser()}. 299 * The default String converter ignores the zone and only parses the field values. 300 * 301 * @param instant the datetime object 302 * @throws IllegalArgumentException if the instant is invalid 303 */ 304 public LocalTime(Object instant) { 305 this(instant, (Chronology) null); 306 } 307 308 /** 309 * Constructs an instance from an Object that represents a datetime, 310 * forcing the time zone to that specified. 311 * <p> 312 * If the object contains no chronology, <code>ISOChronology</code> is used. 313 * If the specified time zone is null, the default zone is used. 314 * Once the constructor is completed, the zone is no longer used. 315 * <p> 316 * The recognised object types are defined in 317 * {@link org.joda.time.convert.ConverterManager ConverterManager} and 318 * include ReadablePartial, ReadableInstant, String, Calendar and Date. 319 * The String formats are described by {@link ISODateTimeFormat#localTimeParser()}. 320 * The default String converter ignores the zone and only parses the field values. 321 * 322 * @param instant the datetime object 323 * @param zone the time zone 324 * @throws IllegalArgumentException if the instant is invalid 325 */ 326 public LocalTime(Object instant, DateTimeZone zone) { 327 PartialConverter converter = ConverterManager.getInstance().getPartialConverter(instant); 328 Chronology chronology = converter.getChronology(instant, zone); 329 chronology = DateTimeUtils.getChronology(chronology); 330 iChronology = chronology.withUTC(); 331 int[] values = converter.getPartialValues(this, instant, chronology, ISODateTimeFormat.localTimeParser()); 332 iLocalMillis = iChronology.getDateTimeMillis(0L, values[0], values[1], values[2], values[3]); 333 } 334 335 /** 336 * Constructs an instance from an Object that represents a datetime, 337 * using the specified chronology. 338 * <p> 339 * If the chronology is null, ISO in the default time zone is used. 340 * Once the constructor is completed, the zone is no longer used. 341 * <p> 342 * The recognised object types are defined in 343 * {@link org.joda.time.convert.ConverterManager ConverterManager} and 344 * include ReadablePartial, ReadableInstant, String, Calendar and Date. 345 * The String formats are described by {@link ISODateTimeFormat#localTimeParser()}. 346 * The default String converter ignores the zone and only parses the field values. 347 * 348 * @param instant the datetime object 349 * @param chronology the chronology 350 * @throws IllegalArgumentException if the instant is invalid 351 */ 352 public LocalTime(Object instant, Chronology chronology) { 353 PartialConverter converter = ConverterManager.getInstance().getPartialConverter(instant); 354 chronology = converter.getChronology(instant, chronology); 355 chronology = DateTimeUtils.getChronology(chronology); 356 iChronology = chronology.withUTC(); 357 int[] values = converter.getPartialValues(this, instant, chronology, ISODateTimeFormat.localTimeParser()); 358 iLocalMillis = iChronology.getDateTimeMillis(0L, values[0], values[1], values[2], values[3]); 359 } 360 361 //----------------------------------------------------------------------- 362 /** 363 * Constructs an instance set to the specified time 364 * using <code>ISOChronology</code>. 365 * 366 * @param hourOfDay the hour of the day 367 * @param minuteOfHour the minute of the hour 368 */ 369 public LocalTime( 370 int hourOfDay, 371 int minuteOfHour) { 372 this(hourOfDay, minuteOfHour, 0, 0, ISOChronology.getInstanceUTC()); 373 } 374 375 /** 376 * Constructs an instance set to the specified time 377 * using <code>ISOChronology</code>. 378 * 379 * @param hourOfDay the hour of the day 380 * @param minuteOfHour the minute of the hour 381 * @param secondOfMinute the second of the minute 382 */ 383 public LocalTime( 384 int hourOfDay, 385 int minuteOfHour, 386 int secondOfMinute) { 387 this(hourOfDay, minuteOfHour, secondOfMinute, 0, ISOChronology.getInstanceUTC()); 388 } 389 390 /** 391 * Constructs an instance set to the specified time 392 * using <code>ISOChronology</code>. 393 * 394 * @param hourOfDay the hour of the day 395 * @param minuteOfHour the minute of the hour 396 * @param secondOfMinute the second of the minute 397 * @param millisOfSecond the millisecond of the second 398 */ 399 public LocalTime( 400 int hourOfDay, 401 int minuteOfHour, 402 int secondOfMinute, 403 int millisOfSecond) { 404 this(hourOfDay, minuteOfHour, secondOfMinute, 405 millisOfSecond, ISOChronology.getInstanceUTC()); 406 } 407 408 /** 409 * Constructs an instance set to the specified time 410 * using the specified chronology, whose zone is ignored. 411 * <p> 412 * If the chronology is null, <code>ISOChronology</code> is used. 413 * 414 * @param hourOfDay the hour of the day 415 * @param minuteOfHour the minute of the hour 416 * @param secondOfMinute the second of the minute 417 * @param millisOfSecond the millisecond of the second 418 * @param chronology the chronology, null means ISOChronology in default zone 419 */ 420 public LocalTime( 421 int hourOfDay, 422 int minuteOfHour, 423 int secondOfMinute, 424 int millisOfSecond, 425 Chronology chronology) { 426 super(); 427 chronology = DateTimeUtils.getChronology(chronology).withUTC(); 428 long instant = chronology.getDateTimeMillis( 429 0L, hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond); 430 iChronology = chronology; 431 iLocalMillis = instant; 432 } 433 434 //----------------------------------------------------------------------- 435 /** 436 * Gets the number of fields in this partial, which is four. 437 * The supported fields are HourOfDay, MinuteOfHour, SecondOfMinute 438 * and MillisOfSecond. 439 * 440 * @return the field count, four 441 */ 442 public int size() { 443 return 4; 444 } 445 446 /** 447 * Gets the field for a specific index in the chronology specified. 448 * <p> 449 * This method must not use any instance variables. 450 * 451 * @param index the index to retrieve 452 * @param chrono the chronology to use 453 * @return the field 454 */ 455 protected DateTimeField getField(int index, Chronology chrono) { 456 switch (index) { 457 case HOUR_OF_DAY: 458 return chrono.hourOfDay(); 459 case MINUTE_OF_HOUR: 460 return chrono.minuteOfHour(); 461 case SECOND_OF_MINUTE: 462 return chrono.secondOfMinute(); 463 case MILLIS_OF_SECOND: 464 return chrono.millisOfSecond(); 465 default: 466 throw new IndexOutOfBoundsException("Invalid index: " + index); 467 } 468 } 469 470 /** 471 * Gets the value of the field at the specifed index. 472 * <p> 473 * This method is required to support the <code>ReadablePartial</code> 474 * interface. The supported fields are HourOfDay, MinuteOfHour, 475 * SecondOfMinute and MillisOfSecond. 476 * 477 * @param index the index, zero to three 478 * @return the value 479 * @throws IndexOutOfBoundsException if the index is invalid 480 */ 481 public int getValue(int index) { 482 switch (index) { 483 case HOUR_OF_DAY: 484 return getChronology().hourOfDay().get(getLocalMillis()); 485 case MINUTE_OF_HOUR: 486 return getChronology().minuteOfHour().get(getLocalMillis()); 487 case SECOND_OF_MINUTE: 488 return getChronology().secondOfMinute().get(getLocalMillis()); 489 case MILLIS_OF_SECOND: 490 return getChronology().millisOfSecond().get(getLocalMillis()); 491 default: 492 throw new IndexOutOfBoundsException("Invalid index: " + index); 493 } 494 } 495 496 //----------------------------------------------------------------------- 497 /** 498 * Get the value of one of the fields of time. 499 * <p> 500 * This method gets the value of the specified field. 501 * For example: 502 * <pre> 503 * DateTime dt = new DateTime(); 504 * int hourOfDay = dt.get(DateTimeFieldType.hourOfDay()); 505 * </pre> 506 * 507 * @param fieldType a field type, usually obtained from DateTimeFieldType, not null 508 * @return the value of that field 509 * @throws IllegalArgumentException if the field type is null 510 */ 511 public int get(DateTimeFieldType fieldType) { 512 if (fieldType == null) { 513 throw new IllegalArgumentException("The DateTimeFieldType must not be null"); 514 } 515 if (isSupported(fieldType) == false) { 516 throw new IllegalArgumentException("Field '" + fieldType + "' is not supported"); 517 } 518 return fieldType.getField(getChronology()).get(getLocalMillis()); 519 } 520 521 /** 522 * Checks if the field type specified is supported by this 523 * local time and chronology. 524 * This can be used to avoid exceptions in {@link #get(DateTimeFieldType)}. 525 * 526 * @param type a field type, usually obtained from DateTimeFieldType 527 * @return true if the field type is supported 528 */ 529 public boolean isSupported(DateTimeFieldType type) { 530 if (type == null) { 531 return false; 532 } 533 if (isSupported(type.getDurationType()) == false) { 534 return false; 535 } 536 DurationFieldType range = type.getRangeDurationType(); 537 return (isSupported(range) || range == DurationFieldType.days()); 538 } 539 540 /** 541 * Checks if the duration type specified is supported by this 542 * local time and chronology. 543 * 544 * @param type a duration type, usually obtained from DurationFieldType 545 * @return true if the field type is supported 546 */ 547 public boolean isSupported(DurationFieldType type) { 548 if (type == null) { 549 return false; 550 } 551 DurationField field = type.getField(getChronology()); 552 if (TIME_DURATION_TYPES.contains(type) || 553 field.getUnitMillis() < getChronology().days().getUnitMillis()) { 554 return field.isSupported(); 555 } 556 return false; 557 } 558 559 //----------------------------------------------------------------------- 560 /** 561 * Gets the local milliseconds from the Java epoch 562 * of 1970-01-01T00:00:00 (not fixed to any specific time zone). 563 * 564 * @return the number of milliseconds since 1970-01-01T00:00:00 565 * @since 1.5 (previously private) 566 */ 567 protected long getLocalMillis() { 568 return iLocalMillis; 569 } 570 571 /** 572 * Gets the chronology of the time. 573 * 574 * @return the Chronology that the time is using 575 */ 576 public Chronology getChronology() { 577 return iChronology; 578 } 579 580 //----------------------------------------------------------------------- 581 /** 582 * Compares this ReadablePartial with another returning true if the chronology, 583 * field types and values are equal. 584 * 585 * @param partial an object to check against 586 * @return true if fields and values are equal 587 */ 588 public boolean equals(Object partial) { 589 // override to perform faster 590 if (this == partial) { 591 return true; 592 } 593 if (partial instanceof LocalTime) { 594 LocalTime other = (LocalTime) partial; 595 if (iChronology.equals(other.iChronology)) { 596 return iLocalMillis == other.iLocalMillis; 597 } 598 } 599 return super.equals(partial); 600 } 601 602 /** 603 * Compares this partial with another returning an integer 604 * indicating the order. 605 * <p> 606 * The fields are compared in order, from largest to smallest. 607 * The first field that is non-equal is used to determine the result. 608 * <p> 609 * The specified object must be a partial instance whose field types 610 * match those of this partial. 611 * <p> 612 * NOTE: This implementation violates the Comparable contract. 613 * This method will accept any instance of ReadablePartial as input. 614 * However, it is possible that some implementations of ReadablePartial 615 * exist that do not extend AbstractPartial, and thus will throw a 616 * ClassCastException if compared in the opposite direction. 617 * The cause of this problem is that ReadablePartial doesn't define 618 * the compareTo() method, however we can't change that until v2.0. 619 * 620 * @param partial an object to check against 621 * @return negative if this is less, zero if equal, positive if greater 622 * @throws ClassCastException if the partial is the wrong class 623 * or if it has field types that don't match 624 * @throws NullPointerException if the partial is null 625 */ 626 public int compareTo(Object partial) { 627 // override to perform faster 628 if (this == partial) { 629 return 0; 630 } 631 if (partial instanceof LocalTime) { 632 LocalTime other = (LocalTime) partial; 633 if (iChronology.equals(other.iChronology)) { 634 return (iLocalMillis < other.iLocalMillis ? -1 : 635 (iLocalMillis == other.iLocalMillis ? 0 : 1)); 636 637 } 638 } 639 return super.compareTo(partial); 640 } 641 642 //----------------------------------------------------------------------- 643 /** 644 * Returns a copy of this time with different local millis. 645 * <p> 646 * The returned object will be a new instance of the same type. 647 * Only the millis will change, the chronology is kept. 648 * The returned object will be either be a new instance or <code>this</code>. 649 * 650 * @param newMillis the new millis, from 1970-01-01T00:00:00 651 * @return a copy of this time with different millis 652 */ 653 LocalTime withLocalMillis(long newMillis) { 654 return (newMillis == getLocalMillis() ? this : new LocalTime(newMillis, getChronology())); 655 } 656 657 //----------------------------------------------------------------------- 658 /** 659 * Returns a copy of this time with the partial set of fields replacing 660 * those from this instance. 661 * <p> 662 * For example, if the partial contains an hour and minute then those two 663 * fields will be changed in the returned instance. 664 * Unsupported fields are ignored. 665 * If the partial is null, then <code>this</code> is returned. 666 * 667 * @param partial the partial set of fields to apply to this time, null ignored 668 * @return a copy of this time with a different set of fields 669 * @throws IllegalArgumentException if any value is invalid 670 */ 671 public LocalTime withFields(ReadablePartial partial) { 672 if (partial == null) { 673 return this; 674 } 675 return withLocalMillis(getChronology().set(partial, getLocalMillis())); 676 } 677 678 /** 679 * Returns a copy of this time with the specified field set 680 * to a new value. 681 * <p> 682 * For example, if the field type is <code>hourOfDay</code> then the hour of day 683 * field would be changed in the returned instance. 684 * If the field type is null, then <code>this</code> is returned. 685 * <p> 686 * These lines are equivalent: 687 * <pre> 688 * LocalTime updated = dt.withHourOfDay(6); 689 * LocalTime updated = dt.withField(DateTimeFieldType.hourOfDay(), 6); 690 * </pre> 691 * 692 * @param fieldType the field type to set, not null 693 * @param value the value to set 694 * @return a copy of this time with the field set 695 * @throws IllegalArgumentException if the value is null or invalid 696 */ 697 public LocalTime withField(DateTimeFieldType fieldType, int value) { 698 if (fieldType == null) { 699 throw new IllegalArgumentException("Field must not be null"); 700 } 701 if (isSupported(fieldType) == false) { 702 throw new IllegalArgumentException("Field '" + fieldType + "' is not supported"); 703 } 704 long instant = fieldType.getField(getChronology()).set(getLocalMillis(), value); 705 return withLocalMillis(instant); 706 } 707 708 /** 709 * Returns a copy of this time with the value of the specified 710 * field increased. 711 * <p> 712 * If the addition is zero or the field is null, then <code>this</code> 713 * is returned. 714 * <p> 715 * If the addition causes the maximum value of the field to be exceeded, 716 * then the value will wrap. Thus 23:59 plus two minutes yields 00:01. 717 * <p> 718 * These lines are equivalent: 719 * <pre> 720 * LocalTime added = dt.plusHours(6); 721 * LocalTime added = dt.withFieldAdded(DurationFieldType.hours(), 6); 722 * </pre> 723 * 724 * @param fieldType the field type to add to, not null 725 * @param amount the amount to add 726 * @return a copy of this time with the field updated 727 * @throws IllegalArgumentException if the value is null or invalid 728 * @throws ArithmeticException if the result exceeds the internal capacity 729 */ 730 public LocalTime withFieldAdded(DurationFieldType fieldType, int amount) { 731 if (fieldType == null) { 732 throw new IllegalArgumentException("Field must not be null"); 733 } 734 if (isSupported(fieldType) == false) { 735 throw new IllegalArgumentException("Field '" + fieldType + "' is not supported"); 736 } 737 if (amount == 0) { 738 return this; 739 } 740 long instant = fieldType.getField(getChronology()).add(getLocalMillis(), amount); 741 return withLocalMillis(instant); 742 } 743 744 //----------------------------------------------------------------------- 745 /** 746 * Returns a copy of this time with the specified period added. 747 * <p> 748 * If the addition is zero, then <code>this</code> is returned. 749 * <p> 750 * This method is typically used to add multiple copies of complex 751 * period instances. Adding one field is best achieved using methods 752 * like {@link #withFieldAdded(DurationFieldType, int)} 753 * or {@link #plusHours(int)}. 754 * 755 * @param period the period to add to this one, null means zero 756 * @param scalar the amount of times to add, such as -1 to subtract once 757 * @return a copy of this time with the period added 758 * @throws ArithmeticException if the result exceeds the internal capacity 759 */ 760 public LocalTime withPeriodAdded(ReadablePeriod period, int scalar) { 761 if (period == null || scalar == 0) { 762 return this; 763 } 764 long instant = getChronology().add(period, getLocalMillis(), scalar); 765 return withLocalMillis(instant); 766 } 767 768 //----------------------------------------------------------------------- 769 /** 770 * Returns a copy of this time with the specified period added. 771 * <p> 772 * If the amount is zero or null, then <code>this</code> is returned. 773 * <p> 774 * This method is typically used to add complex period instances. 775 * Adding one field is best achieved using methods 776 * like {@link #plusHours(int)}. 777 * 778 * @param period the period to add to this one, null means zero 779 * @return a copy of this time with the period added 780 * @throws ArithmeticException if the result exceeds the internal capacity 781 */ 782 public LocalTime plus(ReadablePeriod period) { 783 return withPeriodAdded(period, 1); 784 } 785 786 //----------------------------------------------------------------------- 787 /** 788 * Returns a copy of this time plus the specified number of hours. 789 * <p> 790 * This LocalTime instance is immutable and unaffected by this method call. 791 * <p> 792 * The following three lines are identical in effect: 793 * <pre> 794 * LocalTime added = dt.plusHours(6); 795 * LocalTime added = dt.plus(Period.hours(6)); 796 * LocalTime added = dt.withFieldAdded(DurationFieldType.hours(), 6); 797 * </pre> 798 * 799 * @param hours the amount of hours to add, may be negative 800 * @return the new LocalTime plus the increased hours 801 */ 802 public LocalTime plusHours(int hours) { 803 if (hours == 0) { 804 return this; 805 } 806 long instant = getChronology().hours().add(getLocalMillis(), hours); 807 return withLocalMillis(instant); 808 } 809 810 /** 811 * Returns a copy of this time plus the specified number of minutes. 812 * <p> 813 * This LocalTime instance is immutable and unaffected by this method call. 814 * <p> 815 * The following three lines are identical in effect: 816 * <pre> 817 * LocalTime added = dt.plusMinutes(6); 818 * LocalTime added = dt.plus(Period.minutes(6)); 819 * LocalTime added = dt.withFieldAdded(DurationFieldType.minutes(), 6); 820 * </pre> 821 * 822 * @param minutes the amount of minutes to add, may be negative 823 * @return the new LocalTime plus the increased minutes 824 */ 825 public LocalTime plusMinutes(int minutes) { 826 if (minutes == 0) { 827 return this; 828 } 829 long instant = getChronology().minutes().add(getLocalMillis(), minutes); 830 return withLocalMillis(instant); 831 } 832 833 /** 834 * Returns a copy of this time plus the specified number of seconds. 835 * <p> 836 * This LocalTime instance is immutable and unaffected by this method call. 837 * <p> 838 * The following three lines are identical in effect: 839 * <pre> 840 * LocalTime added = dt.plusSeconds(6); 841 * LocalTime added = dt.plus(Period.seconds(6)); 842 * LocalTime added = dt.withFieldAdded(DurationFieldType.seconds(), 6); 843 * </pre> 844 * 845 * @param seconds the amount of seconds to add, may be negative 846 * @return the new LocalTime plus the increased seconds 847 */ 848 public LocalTime plusSeconds(int seconds) { 849 if (seconds == 0) { 850 return this; 851 } 852 long instant = getChronology().seconds().add(getLocalMillis(), seconds); 853 return withLocalMillis(instant); 854 } 855 856 /** 857 * Returns a copy of this time plus the specified number of millis. 858 * <p> 859 * This LocalTime instance is immutable and unaffected by this method call. 860 * <p> 861 * The following three lines are identical in effect: 862 * <pre> 863 * LocalTime added = dt.plusMillis(6); 864 * LocalTime added = dt.plus(Period.millis(6)); 865 * LocalTime added = dt.withFieldAdded(DurationFieldType.millis(), 6); 866 * </pre> 867 * 868 * @param millis the amount of millis to add, may be negative 869 * @return the new LocalTime plus the increased millis 870 */ 871 public LocalTime plusMillis(int millis) { 872 if (millis == 0) { 873 return this; 874 } 875 long instant = getChronology().millis().add(getLocalMillis(), millis); 876 return withLocalMillis(instant); 877 } 878 879 //----------------------------------------------------------------------- 880 /** 881 * Returns a copy of this time with the specified period taken away. 882 * <p> 883 * If the amount is zero or null, then <code>this</code> is returned. 884 * <p> 885 * This method is typically used to subtract complex period instances. 886 * Subtracting one field is best achieved using methods 887 * like {@link #minusHours(int)}. 888 * 889 * @param period the period to reduce this instant by 890 * @return a copy of this time with the period taken away 891 * @throws ArithmeticException if the result exceeds the internal capacity 892 */ 893 public LocalTime minus(ReadablePeriod period) { 894 return withPeriodAdded(period, -1); 895 } 896 897 //----------------------------------------------------------------------- 898 /** 899 * Returns a copy of this time minus the specified number of hours. 900 * <p> 901 * This LocalTime instance is immutable and unaffected by this method call. 902 * <p> 903 * The following three lines are identical in effect: 904 * <pre> 905 * LocalTime subtracted = dt.minusHours(6); 906 * LocalTime subtracted = dt.minus(Period.hours(6)); 907 * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.hours(), -6); 908 * </pre> 909 * 910 * @param hours the amount of hours to subtract, may be negative 911 * @return the new LocalTime minus the increased hours 912 */ 913 public LocalTime minusHours(int hours) { 914 if (hours == 0) { 915 return this; 916 } 917 long instant = getChronology().hours().subtract(getLocalMillis(), hours); 918 return withLocalMillis(instant); 919 } 920 921 /** 922 * Returns a copy of this time minus the specified number of minutes. 923 * <p> 924 * This LocalTime instance is immutable and unaffected by this method call. 925 * <p> 926 * The following three lines are identical in effect: 927 * <pre> 928 * LocalTime subtracted = dt.minusMinutes(6); 929 * LocalTime subtracted = dt.minus(Period.minutes(6)); 930 * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.minutes(), -6); 931 * </pre> 932 * 933 * @param minutes the amount of minutes to subtract, may be negative 934 * @return the new LocalTime minus the increased minutes 935 */ 936 public LocalTime minusMinutes(int minutes) { 937 if (minutes == 0) { 938 return this; 939 } 940 long instant = getChronology().minutes().subtract(getLocalMillis(), minutes); 941 return withLocalMillis(instant); 942 } 943 944 /** 945 * Returns a copy of this time minus the specified number of seconds. 946 * <p> 947 * This LocalTime instance is immutable and unaffected by this method call. 948 * <p> 949 * The following three lines are identical in effect: 950 * <pre> 951 * LocalTime subtracted = dt.minusSeconds(6); 952 * LocalTime subtracted = dt.minus(Period.seconds(6)); 953 * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.seconds(), -6); 954 * </pre> 955 * 956 * @param seconds the amount of seconds to subtract, may be negative 957 * @return the new LocalTime minus the increased seconds 958 */ 959 public LocalTime minusSeconds(int seconds) { 960 if (seconds == 0) { 961 return this; 962 } 963 long instant = getChronology().seconds().subtract(getLocalMillis(), seconds); 964 return withLocalMillis(instant); 965 } 966 967 /** 968 * Returns a copy of this time minus the specified number of millis. 969 * <p> 970 * This LocalTime instance is immutable and unaffected by this method call. 971 * <p> 972 * The following three lines are identical in effect: 973 * <pre> 974 * LocalTime subtracted = dt.minusMillis(6); 975 * LocalTime subtracted = dt.minus(Period.millis(6)); 976 * LocalTime subtracted = dt.withFieldAdded(DurationFieldType.millis(), -6); 977 * </pre> 978 * 979 * @param millis the amount of millis to subtract, may be negative 980 * @return the new LocalTime minus the increased millis 981 */ 982 public LocalTime minusMillis(int millis) { 983 if (millis == 0) { 984 return this; 985 } 986 long instant = getChronology().millis().subtract(getLocalMillis(), millis); 987 return withLocalMillis(instant); 988 } 989 990 //----------------------------------------------------------------------- 991 /** 992 * Gets the property object for the specified type, which contains 993 * many useful methods. 994 * 995 * @param fieldType the field type to get the chronology for 996 * @return the property object 997 * @throws IllegalArgumentException if the field is null or unsupported 998 */ 999 public Property property(DateTimeFieldType fieldType) { 1000 if (fieldType == null) { 1001 throw new IllegalArgumentException("The DateTimeFieldType must not be null"); 1002 } 1003 if (isSupported(fieldType) == false) { 1004 throw new IllegalArgumentException("Field '" + fieldType + "' is not supported"); 1005 } 1006 return new Property(this, fieldType.getField(getChronology())); 1007 } 1008 1009 //----------------------------------------------------------------------- 1010 /** 1011 * Get the hour of day field value. 1012 * 1013 * @return the hour of day 1014 */ 1015 public int getHourOfDay() { 1016 return getChronology().hourOfDay().get(getLocalMillis()); 1017 } 1018 1019 /** 1020 * Get the minute of hour field value. 1021 * 1022 * @return the minute of hour 1023 */ 1024 public int getMinuteOfHour() { 1025 return getChronology().minuteOfHour().get(getLocalMillis()); 1026 } 1027 1028 /** 1029 * Get the second of minute field value. 1030 * 1031 * @return the second of minute 1032 */ 1033 public int getSecondOfMinute() { 1034 return getChronology().secondOfMinute().get(getLocalMillis()); 1035 } 1036 1037 /** 1038 * Get the millis of second field value. 1039 * 1040 * @return the millis of second 1041 */ 1042 public int getMillisOfSecond() { 1043 return getChronology().millisOfSecond().get(getLocalMillis()); 1044 } 1045 1046 /** 1047 * Get the millis of day field value. 1048 * 1049 * @return the millis of day 1050 */ 1051 public int getMillisOfDay() { 1052 return getChronology().millisOfDay().get(getLocalMillis()); 1053 } 1054 1055 //----------------------------------------------------------------------- 1056 /** 1057 * Returns a copy of this time with the hour of day field updated. 1058 * <p> 1059 * LocalTime is immutable, so there are no set methods. 1060 * Instead, this method returns a new instance with the value of 1061 * hour of day changed. 1062 * 1063 * @param hour the hour of day to set 1064 * @return a copy of this object with the field set 1065 * @throws IllegalArgumentException if the value is invalid 1066 */ 1067 public LocalTime withHourOfDay(int hour) { 1068 return withLocalMillis(getChronology().hourOfDay().set(getLocalMillis(), hour)); 1069 } 1070 1071 /** 1072 * Returns a copy of this time with the minute of hour field updated. 1073 * <p> 1074 * LocalTime is immutable, so there are no set methods. 1075 * Instead, this method returns a new instance with the value of 1076 * minute of hour changed. 1077 * 1078 * @param minute the minute of hour to set 1079 * @return a copy of this object with the field set 1080 * @throws IllegalArgumentException if the value is invalid 1081 */ 1082 public LocalTime withMinuteOfHour(int minute) { 1083 return withLocalMillis(getChronology().minuteOfHour().set(getLocalMillis(), minute)); 1084 } 1085 1086 /** 1087 * Returns a copy of this time with the second of minute field updated. 1088 * <p> 1089 * LocalTime is immutable, so there are no set methods. 1090 * Instead, this method returns a new instance with the value of 1091 * second of minute changed. 1092 * 1093 * @param second the second of minute to set 1094 * @return a copy of this object with the field set 1095 * @throws IllegalArgumentException if the value is invalid 1096 */ 1097 public LocalTime withSecondOfMinute(int second) { 1098 return withLocalMillis(getChronology().secondOfMinute().set(getLocalMillis(), second)); 1099 } 1100 1101 /** 1102 * Returns a copy of this time with the millis of second field updated. 1103 * <p> 1104 * LocalTime is immutable, so there are no set methods. 1105 * Instead, this method returns a new instance with the value of 1106 * millis of second changed. 1107 * 1108 * @param millis the millis of second to set 1109 * @return a copy of this object with the field set 1110 * @throws IllegalArgumentException if the value is invalid 1111 */ 1112 public LocalTime withMillisOfSecond(int millis) { 1113 return withLocalMillis(getChronology().millisOfSecond().set(getLocalMillis(), millis)); 1114 } 1115 1116 /** 1117 * Returns a copy of this time with the millis of day field updated. 1118 * <p> 1119 * LocalTime is immutable, so there are no set methods. 1120 * Instead, this method returns a new instance with the value of 1121 * millis of day changed. 1122 * 1123 * @param millis the millis of day to set 1124 * @return a copy of this object with the field set 1125 * @throws IllegalArgumentException if the value is invalid 1126 */ 1127 public LocalTime withMillisOfDay(int millis) { 1128 return withLocalMillis(getChronology().millisOfDay().set(getLocalMillis(), millis)); 1129 } 1130 1131 //----------------------------------------------------------------------- 1132 /** 1133 * Get the hour of day field property which provides access to advanced functionality. 1134 * 1135 * @return the hour of day property 1136 */ 1137 public Property hourOfDay() { 1138 return new Property(this, getChronology().hourOfDay()); 1139 } 1140 1141 /** 1142 * Get the minute of hour field property which provides access to advanced functionality. 1143 * 1144 * @return the minute of hour property 1145 */ 1146 public Property minuteOfHour() { 1147 return new Property(this, getChronology().minuteOfHour()); 1148 } 1149 1150 /** 1151 * Get the second of minute field property which provides access to advanced functionality. 1152 * 1153 * @return the second of minute property 1154 */ 1155 public Property secondOfMinute() { 1156 return new Property(this, getChronology().secondOfMinute()); 1157 } 1158 1159 /** 1160 * Get the millis of second property which provides access to advanced functionality. 1161 * 1162 * @return the millis of second property 1163 */ 1164 public Property millisOfSecond() { 1165 return new Property(this, getChronology().millisOfSecond()); 1166 } 1167 1168 /** 1169 * Get the millis of day property which provides access to advanced functionality. 1170 * 1171 * @return the millis of day property 1172 */ 1173 public Property millisOfDay() { 1174 return new Property(this, getChronology().millisOfDay()); 1175 } 1176 1177 //----------------------------------------------------------------------- 1178 /** 1179 * Converts this LocalTime to a full datetime using the default time zone 1180 * setting the time fields from this instance and the date fields from 1181 * the current date. 1182 * 1183 * @return this time as a datetime using todays date 1184 */ 1185 public DateTime toDateTimeToday() { 1186 return toDateTimeToday(null); 1187 } 1188 1189 /** 1190 * Converts this LocalTime to a full datetime using the specified time zone 1191 * setting the time fields from this instance and the date fields from 1192 * the current time. 1193 * <p> 1194 * This method uses the chronology from this instance plus the time zone 1195 * specified. 1196 * 1197 * @param zone the zone to use, null means default 1198 * @return this time as a datetime using todays date 1199 */ 1200 public DateTime toDateTimeToday(DateTimeZone zone) { 1201 Chronology chrono = getChronology().withZone(zone); 1202 long instantMillis = DateTimeUtils.currentTimeMillis(); 1203 long resolved = chrono.set(this, instantMillis); 1204 return new DateTime(resolved, chrono); 1205 } 1206 1207 //----------------------------------------------------------------------- 1208 /** 1209 * Output the time in ISO8601 format (HH:mm:ss.SSSZZ). 1210 * 1211 * @return ISO8601 time formatted string. 1212 */ 1213 public String toString() { 1214 return ISODateTimeFormat.time().print(this); 1215 } 1216 1217 /** 1218 * Output the time using the specified format pattern. 1219 * 1220 * @param pattern the pattern specification, null means use <code>toString</code> 1221 * @see org.joda.time.format.DateTimeFormat 1222 */ 1223 public String toString(String pattern) { 1224 if (pattern == null) { 1225 return toString(); 1226 } 1227 return DateTimeFormat.forPattern(pattern).print(this); 1228 } 1229 1230 /** 1231 * Output the time using the specified format pattern. 1232 * 1233 * @param pattern the pattern specification, null means use <code>toString</code> 1234 * @param locale Locale to use, null means default 1235 * @see org.joda.time.format.DateTimeFormat 1236 */ 1237 public String toString(String pattern, Locale locale) throws IllegalArgumentException { 1238 if (pattern == null) { 1239 return toString(); 1240 } 1241 return DateTimeFormat.forPattern(pattern).withLocale(locale).print(this); 1242 } 1243 1244 //----------------------------------------------------------------------- 1245 /** 1246 * LocalTime.Property binds a LocalTime to a DateTimeField allowing 1247 * powerful datetime functionality to be easily accessed. 1248 * <p> 1249 * The simplest use of this class is as an alternative get method, here used to 1250 * get the minute '30'. 1251 * <pre> 1252 * LocalTime dt = new LocalTime(12, 30); 1253 * int year = dt.minuteOfHour().get(); 1254 * </pre> 1255 * <p> 1256 * Methods are also provided that allow time modification. These return 1257 * new instances of LocalTime - they do not modify the original. The example 1258 * below yields two independent immutable date objects 2 hours apart. 1259 * <pre> 1260 * LocalTime dt1230 = new LocalTime(12, 30); 1261 * LocalTime dt1430 = dt1230.hourOfDay().setCopy(14); 1262 * </pre> 1263 * <p> 1264 * LocalTime.Property itself is thread-safe and immutable, as well as the 1265 * LocalTime being operated on. 1266 * 1267 * @author Stephen Colebourne 1268 * @author Brian S O'Neill 1269 * @since 1.3 1270 */ 1271 public static final class Property extends AbstractReadableInstantFieldProperty { 1272 1273 /** Serialization version */ 1274 private static final long serialVersionUID = -325842547277223L; 1275 1276 /** The instant this property is working against */ 1277 private transient LocalTime iInstant; 1278 /** The field this property is working against */ 1279 private transient DateTimeField iField; 1280 1281 /** 1282 * Constructor. 1283 * 1284 * @param instant the instant to set 1285 * @param field the field to use 1286 */ 1287 Property(LocalTime instant, DateTimeField field) { 1288 super(); 1289 iInstant = instant; 1290 iField = field; 1291 } 1292 1293 /** 1294 * Writes the property in a safe serialization format. 1295 */ 1296 private void writeObject(ObjectOutputStream oos) throws IOException { 1297 oos.writeObject(iInstant); 1298 oos.writeObject(iField.getType()); 1299 } 1300 1301 /** 1302 * Reads the property from a safe serialization format. 1303 */ 1304 private void readObject(ObjectInputStream oos) throws IOException, ClassNotFoundException { 1305 iInstant = (LocalTime) oos.readObject(); 1306 DateTimeFieldType type = (DateTimeFieldType) oos.readObject(); 1307 iField = type.getField(iInstant.getChronology()); 1308 } 1309 1310 //----------------------------------------------------------------------- 1311 /** 1312 * Gets the field being used. 1313 * 1314 * @return the field 1315 */ 1316 public DateTimeField getField() { 1317 return iField; 1318 } 1319 1320 /** 1321 * Gets the milliseconds of the time that this property is linked to. 1322 * 1323 * @return the milliseconds 1324 */ 1325 protected long getMillis() { 1326 return iInstant.getLocalMillis(); 1327 } 1328 1329 /** 1330 * Gets the chronology of the datetime that this property is linked to. 1331 * 1332 * @return the chronology 1333 * @since 1.4 1334 */ 1335 protected Chronology getChronology() { 1336 return iInstant.getChronology(); 1337 } 1338 1339 /** 1340 * Gets the LocalTime object linked to this property. 1341 * 1342 * @return the linked LocalTime 1343 */ 1344 public LocalTime getLocalTime() { 1345 return iInstant; 1346 } 1347 1348 //----------------------------------------------------------------------- 1349 /** 1350 * Adds to this field in a copy of this LocalTime. 1351 * <p> 1352 * The LocalTime attached to this property is unchanged by this call. 1353 * 1354 * @param value the value to add to the field in the copy 1355 * @return a copy of the LocalTime with the field value changed 1356 */ 1357 public LocalTime addCopy(int value) { 1358 return iInstant.withLocalMillis(iField.add(iInstant.getLocalMillis(), value)); 1359 } 1360 1361 /** 1362 * Adds to this field in a copy of this LocalTime. 1363 * If the addition exceeds the maximum value (eg. 23:59) it will 1364 * wrap to the minimum value (eg. 00:00). 1365 * <p> 1366 * The LocalTime attached to this property is unchanged by this call. 1367 * 1368 * @param value the value to add to the field in the copy 1369 * @return a copy of the LocalTime with the field value changed 1370 */ 1371 public LocalTime addCopy(long value) { 1372 return iInstant.withLocalMillis(iField.add(iInstant.getLocalMillis(), value)); 1373 } 1374 1375 /** 1376 * Adds to this field in a copy of this LocalTime. 1377 * If the addition exceeds the maximum value (eg. 23:59) then 1378 * an exception will be thrown. 1379 * Contrast this behaviour to {@link #addCopy(int)}. 1380 * <p> 1381 * The LocalTime attached to this property is unchanged by this call. 1382 * 1383 * @param value the value to add to the field in the copy 1384 * @return a copy of the LocalTime with the field value changed 1385 * @throws IllegalArgumentException if the result is invalid 1386 */ 1387 public LocalTime addNoWrapToCopy(int value) { 1388 long millis = iField.add(iInstant.getLocalMillis(), value); 1389 long rounded = iInstant.getChronology().millisOfDay().get(millis); 1390 if (rounded != millis) { 1391 throw new IllegalArgumentException("The addition exceeded the boundaries of LocalTime"); 1392 } 1393 return iInstant.withLocalMillis(millis); 1394 } 1395 1396 /** 1397 * Adds to this field, possibly wrapped, in a copy of this LocalTime. 1398 * A field wrapped operation only changes this field. 1399 * Thus 10:59 plusWrapField one minute goes to 10:00. 1400 * <p> 1401 * The LocalTime attached to this property is unchanged by this call. 1402 * 1403 * @param value the value to add to the field in the copy 1404 * @return a copy of the LocalTime with the field value changed 1405 * @throws IllegalArgumentException if the value isn't valid 1406 */ 1407 public LocalTime addWrapFieldToCopy(int value) { 1408 return iInstant.withLocalMillis(iField.addWrapField(iInstant.getLocalMillis(), value)); 1409 } 1410 1411 //----------------------------------------------------------------------- 1412 /** 1413 * Sets this field in a copy of the LocalTime. 1414 * <p> 1415 * The LocalTime attached to this property is unchanged by this call. 1416 * 1417 * @param value the value to set the field in the copy to 1418 * @return a copy of the LocalTime with the field value changed 1419 * @throws IllegalArgumentException if the value isn't valid 1420 */ 1421 public LocalTime setCopy(int value) { 1422 return iInstant.withLocalMillis(iField.set(iInstant.getLocalMillis(), value)); 1423 } 1424 1425 /** 1426 * Sets this field in a copy of the LocalTime to a parsed text value. 1427 * <p> 1428 * The LocalTime attached to this property is unchanged by this call. 1429 * 1430 * @param text the text value to set 1431 * @param locale optional locale to use for selecting a text symbol 1432 * @return a copy of the LocalTime with the field value changed 1433 * @throws IllegalArgumentException if the text value isn't valid 1434 */ 1435 public LocalTime setCopy(String text, Locale locale) { 1436 return iInstant.withLocalMillis(iField.set(iInstant.getLocalMillis(), text, locale)); 1437 } 1438 1439 /** 1440 * Sets this field in a copy of the LocalTime to a parsed text value. 1441 * <p> 1442 * The LocalTime attached to this property is unchanged by this call. 1443 * 1444 * @param text the text value to set 1445 * @return a copy of the LocalTime with the field value changed 1446 * @throws IllegalArgumentException if the text value isn't valid 1447 */ 1448 public LocalTime setCopy(String text) { 1449 return setCopy(text, null); 1450 } 1451 1452 //----------------------------------------------------------------------- 1453 /** 1454 * Returns a new LocalTime with this field set to the maximum value 1455 * for this field. 1456 * <p> 1457 * The LocalTime attached to this property is unchanged by this call. 1458 * 1459 * @return a copy of the LocalTime with this field set to its maximum 1460 */ 1461 public LocalTime withMaximumValue() { 1462 return setCopy(getMaximumValue()); 1463 } 1464 1465 /** 1466 * Returns a new LocalTime with this field set to the minimum value 1467 * for this field. 1468 * <p> 1469 * The LocalTime attached to this property is unchanged by this call. 1470 * 1471 * @return a copy of the LocalTime with this field set to its minimum 1472 */ 1473 public LocalTime withMinimumValue() { 1474 return setCopy(getMinimumValue()); 1475 } 1476 1477 //----------------------------------------------------------------------- 1478 /** 1479 * Rounds to the lowest whole unit of this field on a copy of this 1480 * LocalTime. 1481 * <p> 1482 * For example, rounding floor on the hourOfDay field of a LocalTime 1483 * where the time is 10:30 would result in new LocalTime with the 1484 * time of 10:00. 1485 * 1486 * @return a copy of the LocalTime with the field value changed 1487 */ 1488 public LocalTime roundFloorCopy() { 1489 return iInstant.withLocalMillis(iField.roundFloor(iInstant.getLocalMillis())); 1490 } 1491 1492 /** 1493 * Rounds to the highest whole unit of this field on a copy of this 1494 * LocalTime. 1495 * <p> 1496 * For example, rounding floor on the hourOfDay field of a LocalTime 1497 * where the time is 10:30 would result in new LocalTime with the 1498 * time of 11:00. 1499 * 1500 * @return a copy of the LocalTime with the field value changed 1501 */ 1502 public LocalTime roundCeilingCopy() { 1503 return iInstant.withLocalMillis(iField.roundCeiling(iInstant.getLocalMillis())); 1504 } 1505 1506 /** 1507 * Rounds to the nearest whole unit of this field on a copy of this 1508 * LocalTime, favoring the floor if halfway. 1509 * 1510 * @return a copy of the LocalTime with the field value changed 1511 */ 1512 public LocalTime roundHalfFloorCopy() { 1513 return iInstant.withLocalMillis(iField.roundHalfFloor(iInstant.getLocalMillis())); 1514 } 1515 1516 /** 1517 * Rounds to the nearest whole unit of this field on a copy of this 1518 * LocalTime, favoring the ceiling if halfway. 1519 * 1520 * @return a copy of the LocalTime with the field value changed 1521 */ 1522 public LocalTime roundHalfCeilingCopy() { 1523 return iInstant.withLocalMillis(iField.roundHalfCeiling(iInstant.getLocalMillis())); 1524 } 1525 1526 /** 1527 * Rounds to the nearest whole unit of this field on a copy of this 1528 * LocalTime. If halfway, the ceiling is favored over the floor 1529 * only if it makes this field's value even. 1530 * 1531 * @return a copy of the LocalTime with the field value changed 1532 */ 1533 public LocalTime roundHalfEvenCopy() { 1534 return iInstant.withLocalMillis(iField.roundHalfEven(iInstant.getLocalMillis())); 1535 } 1536 } 1537 1538 }